﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

//using Tencent.OA.Common.Web.Security;
using Tencent.OA.Framework.RightWay.Entity;
using Tencent.OA.Framework.RightWay.Proxy;
using Tencent.OA.FM.Common;
using Tencent.OA.Framework.Organization;
using System.IO;
using Tencent.OA.App;
using System.Web.Caching;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using Tencent.OA.ACM.Proxy;
using System.Configuration;

namespace Tencent.OA.ACM.App
{
    public class MvcApplication : System.Web.HttpApplication
    {
        private const string AppUnity4AppContainerKey = "applicationUnity4AppContainer";
        /// <summary>
        /// 部门缓存Key
        /// </summary>
        public const string DEPT_CACHE_KEY = "AllDept";
        /// <summary>
        /// 人员缓存Key
        /// </summary>
        public const string STAFF_CACHE_KEY = "AllStaff";

        /// <summary>
        /// 部门缓存Key
        /// </summary>
        public const string SYS_CACHE_KEY = "AllSys";


        protected void Application_Start()
        {
            MvcRegistration.RegisterModelBinders(ModelBinders.Binders);
            MvcRegistration.RegisterRoutes(RouteTable.Routes);
            LoggerProvider.CurrentLogger.Info("----- Application_Start ------");
        }

        protected void Application_Error(object sender, EventArgs e)
        {
            Exception ex = Server.GetLastError().GetBaseException();
            if (ex.InnerException != null)
            {
                ex = ex.InnerException;
            }
            LoggerProvider.CurrentLogger.Error(ex);
        }


        protected void Application_End(object sender, EventArgs e)
        {
            DisposeUnity();
            LoggerProvider.CurrentLogger.Info("----- Application_End ------");
        }

        #region Unity Block

        private IUnityContainer ApplicationUnity4AppContainer
        {
            get
            {
                return (IUnityContainer)this.Application[AppUnity4AppContainerKey];
            }
            set
            {
                this.Application[AppUnity4AppContainerKey] = value;
            }
        }

        private static IUnityContainer GlobalUnityContainer
        {
            get;
            set;
        }
        public static T GetIMPL<T>()
        {
            if (GlobalUnityContainer == null)
                return default(T);
            return GlobalUnityContainer.Resolve<T>();
        }

        //private void LoadAndInitUnity()
        //{
        //    IUnityContainer applicationContainer = new UnityContainer();
        //    applicationContainer.LoadConfiguration("unity4app");
        //    ApplicationUnity4AppContainer = applicationContainer;
        //    GlobalUnityContainer = applicationContainer;
        //    //Set container for Controller Factory
        //    MvcUnityContainer.Container = applicationContainer;
        //    //Set Controller Factory as UnityControllerFactory
        //    ControllerBuilder.Current.SetControllerFactory(typeof(UnityControllerFactory));
        //}

        private void DisposeUnity()
        {
            IUnityContainer applicationContainer = this.ApplicationUnity4AppContainer;
            if (applicationContainer != null)
            {
                applicationContainer.Dispose();
                this.ApplicationUnity4AppContainer = null;
            }
        }

        #endregion

        public override void Init()
        {
            base.Init();
            this.EndRequest += new EventHandler(MvcApplication_EndRequest);
        }

        void MvcApplication_EndRequest(object sender, EventArgs e)
        {
            ProxyManager.DistoryAllProxy();
        }


        #region /*加载员工和部门信息到全局缓存*/

        /*private void LoadingStaffAndDeptInfo(HttpApplication app)
        {
            System.Threading.ThreadPool.SetMaxThreads(512, 512);
            System.Threading.ThreadPool.SetMinThreads(256, 256);

            // 从AllDept.dat文件中加载所有的员工信息并压入Application缓存中
            //
            List<Staff> staffList;
            string dataFilePath = app.Context.Server.MapPath("~/AllStaff.dat");
            try
            {
                if (File.Exists(dataFilePath) &&
                ApplicationCache.Contains(STAFF_CACHE_KEY) &&
                ApplicationCache[STAFF_CACHE_KEY] != null &&
                ApplicationCache[STAFF_CACHE_KEY] is List<Staff>)
                {
                    byte[] data;
                    lock (m_staffDataLock)
                    {
                        FileStream sr = new FileStream(dataFilePath, FileMode.Open);
                        data = new byte[sr.Length];
                        sr.Read(data, 0, (int)sr.Length);
                        sr.Close();
                    }
                    staffList = Utils.BytesToObjArr<Staff>(data).ToList();
                }
                else
                {
                    staffList = Staff.GetAllStaff(true);
                    var data = Utils.ObjArrToBytes(staffList.ToArray());
                    lock (m_staffDataLock)
                    {
                        FileStream sw = new FileStream(dataFilePath, FileMode.Create, FileAccess.Write);
                        sw.Write(data, 0, data.Length);
                        sw.Close();
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            var q = from s in staffList orderby s.StatusId, s.EnglishName select s;
            //Modified By wwz@2011-2-25 
            //app.Application["AllStaff"] = q.ToList();
            ApplicationCache.Add(STAFF_CACHE_KEY, q.ToList());
            // 从AllDept.dat文件中加载所有的员工信息并压入Application缓存中
            //          
            
            List<Dept> deptList;
            dataFilePath = app.Context.Server.MapPath("~/AllDept.dat");
            if (File.Exists(dataFilePath) && 
                ApplicationCache.Contains(DEPT_CACHE_KEY) && 
                ApplicationCache[DEPT_CACHE_KEY] != null && 
                ApplicationCache[DEPT_CACHE_KEY] is List<Dept>)
            {
                byte[] data;
                lock (m_staffDataLock)
                {
                    FileStream sr = new FileStream(dataFilePath, FileMode.Open);
                    data = new byte[sr.Length];
                    sr.Read(data, 0, (int)sr.Length);
                    sr.Close();
                }
                deptList = Utils.BytesToObjArr<Dept>(data).ToList();
            }
            else
            {
                deptList = Tencent.OA.Framework.Organization.Dept.GetAllDepts(false);
                var data = Tencent.OA.FM.Common.Utils.ObjArrToBytes(deptList.ToArray());
                lock (m_staffDataLock)
                {
                    System.IO.FileStream sw = new System.IO.FileStream(dataFilePath, System.IO.FileMode.Create, System.IO.FileAccess.Write);
                    sw.Write(data, 0, data.Length);
                    sw.Close();
                }
            }
            var dq = from s in deptList orderby s.Name select s;
            //Modified By wwz@2011-2-25 
            //app.Application["AllDept"] = dq.ToList();
            ApplicationCache.Add(DEPT_CACHE_KEY, dq.ToList());
        }*/

        #endregion

        /// <summary>
        /// 取所有部门
        /// </summary>
        /// <returns></returns>
        public static List<Dept> GetAllDept()
        {
            List<Dept> deptList;
            if (LoadCachedData(DEPT_CACHE_KEY, () => (List<Dept>)Dept.GetAllDepts(false), out deptList))
                return deptList;
            return new List<Dept>();
            //List<Dept> deptList = ApplicationCache[DEPT_CACHE_KEY] as List<Dept>;
            //if (deptList == null)
            //{
            //    deptList = Tencent.OA.Framework.Organization.Dept.GetAllDepts(false);
            //    ApplicationCache.Add(DEPT_CACHE_KEY, deptList, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, 20, 0), CacheItemPriority.High, null);
            //}
            //return deptList;
        }

        /// <summary>
        /// 取所有员工
        /// </summary>
        /// <returns></returns>
        public static List<Staff> GetAllStaff()
        {
            List<Staff> staffList;
            if (LoadCachedData(STAFF_CACHE_KEY, () => (List<Staff>)Staff.GetAllStaff(true), out staffList))
                return staffList;
            return new List<Staff>();
        }

        /// <summary>
        /// 尝试从缓存获取 T 类型的数据对象，如果缓存中没有该对象，则调用委托loadFromRepository获取数据。
        /// </summary>
        /// <typeparam name="T">指示需要从缓存中获取的数据类型。</typeparam>
        /// <param name="cacheKey">缓存键，如果缓存中不存在该键，将调用loadFromRepository委托获取对象数据，并加入到缓存中。</param>
        /// <param name="loadFromRepository">一个委托，用于从数据源等获取数据。</param>
        /// <param name="value">需要获取的数据对象。</param>
        /// <returns>缓存中存在数据对象或调用loadFromRepository成功，则返回true，出现异常时返回false。</returns>
        internal static bool LoadCachedData<T>(string cacheKey, Func<T> loadFromRepository, out T value)
        {
            try
            {
                value = (T)HttpRuntime.Cache[cacheKey];
                if (value == null)
                {
                    value = loadFromRepository();
                    HttpRuntime.Cache.Add(cacheKey, value, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, 20, 0), CacheItemPriority.High, null);
                }
                return true;
            }
            catch
            {
                value = default(T);
            }
            return false;
        }

        #region 系统变量

        //internal static TencentTravelSection TravelConfigSection = TencentTravelSection.GetSection();

        /// <summary>
        /// 获取系统名称
        /// </summary>
        public static string SystemName
        {
            get
            {
                //return TravelConfigSection.SystemName;
                return System.Configuration.ConfigurationManager.AppSettings["SystemName"];
            }
        }
        /// <summary>
        /// 获取系统ID
        /// </summary>
        public static int SystemID
        {
            get
            {
                // return TravelConfigSection.SystemID;
                return Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["SystemID"]);
            }
        }
        /// <summary>
        /// 站点地址
        /// </summary>
        public static string HomePage
        {
            get
            {
                string homePage = System.Configuration.ConfigurationManager.AppSettings["HomePage"];
                return homePage.EndsWith("/")?homePage:homePage+"/";
            }
        }
        /// <summary>
        /// 缓存目录
        /// </summary>
        public static string WebCacheDir
        {
            get
            {
                return HttpContext.Current.Server.MapPath("~/caches"); //System.Configuration.ConfigurationManager.AppSettings["WebCacheDir"];
            }
        }
        /// <summary>
        /// 路线/站点的刷卡人数/列表的统计天数
        /// </summary>
        public static int StationEmpsStatDays
        {
            get
            {
                int days = 1;
                Int32.TryParse(System.Configuration.ConfigurationManager.AppSettings["StationEmpsStatDays"],out days);
                return days;
            }
        }

        /// <summary>
        /// 邮件模板目录
        /// </summary>
        public static string MailTempDir
        {
            get
            {
                return HttpContext.Current.Server.MapPath("~/Content/Template");
            }
        }
        /// <summary>
        /// 上传路径
        /// </summary>
        public static string UploadPath
        {
            get
            {
                string path=System.Configuration.ConfigurationManager.AppSettings["UploadPath"];
                if (path.StartsWith("~"))
                    return HttpContext.Current.Server.MapPath(path);
                else
                    return path;
            }
        }
        /// <summary>
        /// 是否发送邮件提醒
        /// </summary>
        public static bool IsSendMail
        {
            get { return bool.Parse((ConfigurationManager.AppSettings["IsSendMail"])); }
        }

        /// <summary>
        /// 是否发送手机短信提醒
        /// </summary>
        public static bool IsSendSMS
        {
            get { return bool.Parse((ConfigurationManager.AppSettings["IsSendSMS"])); }
        }

        /// <summary>
        /// 是否发送outlook日期提醒
        /// </summary>
        public static bool IsSendRTX
        {
            get { return bool.Parse((ConfigurationManager.AppSettings["IsSendRTX"])); }
        }

        /// <summary>
        /// 是否发送线路变动通知
        /// </summary>
        public static bool IsSendNotice
        {
            get { return bool.Parse((ConfigurationManager.AppSettings["IsSendNotice"])); }
        }
         
        /// <summary>
        /// 邮件发送人
        /// </summary>
        public static string EmailSender
        {
            get { return ConfigurationManager.AppSettings["MailSenderName"]; }
        }

        /// <summary>
        /// 邮件模板文件数组,依次是email、短信、rtx
        /// </summary>
        public static string[] NoticeTemplateFiles
        {
            get { return ConfigurationManager.AppSettings["NoticeTemplate"].Split(','); }
        }

        /// <summary>
        /// 获取上传图片后缀
        /// </summary>
        public static string IsSuffix
        {
            get { return System.Configuration.ConfigurationManager.AppSettings["FileType"]; }
        }
        #endregion

    }

    #region unity setting

    public class UnityControllerFactory : DefaultControllerFactory
    {
        protected override IController GetControllerInstance(RequestContext reqContext, Type controllerType)
        {
            if (controllerType == null)
            {
                throw new HttpException(404, String.Format("The controller for path '{0}' could not be found or it does not implement IController.", reqContext.HttpContext.Request.Path));
            }
            if (!typeof(IController).IsAssignableFrom(controllerType))
                throw new ArgumentException(string.Format("Type requested is not a controller: {0}", controllerType.Name), "controllerType");
            try
            {
                return MvcUnityContainer.Container.Resolve(controllerType) as IController;
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException(String.Format("Error resolving controller {0}", controllerType.Name), ex);
            }
        }
    }

    public static class MvcUnityContainer
    {
        public static IUnityContainer Container { get; set; }
    }

    #endregion

}